#include <stdio.h>
#include "course.h"

void EditGrade(struct Course *courses)
{
    while (1)
    {
        // print and count courses
        int courseCount = displayCourses(courses);

        // course selection
        int sel;
        printf("Enter a number to edit the related course grades or any other key back: ");
        scanf("%d", &sel);

        // display grade of selected course
        if (sel > 0 && sel <= courseCount)
            selectedCourse(courses, sel - 1);
        // exit on other keys
        else
            return;
    }
    return;
}

void selectedCourse(struct Course *courses, int sel)
{
    while (1)
    {
        displayHeader(courses[sel]);
        // display and count grade items
        int gradeitemCount = getGradeItemNum(courses[sel]);
        for (int i = 0; i < gradeitemCount; i++)
        {
            displayGradeItem(courses[sel].gradeitems[i], i + 1);
        }
        displayFooter();

        // grade item selection
        int gisel;
        printf("Enter the No. of an Item whose grades to be edited or any other key back: ");
        scanf("%d", &gisel);
        if (gisel > 0 && gisel <= gradeitemCount)
            editCourseGrade(&courses[sel], gisel - 1);
        // exit on other keys
        else
            return;
    }
    return;
}

void editCourseGrade(struct Course *course, int gisel)
{
    while (1)
    {
        displayHeader(*course);
        displayGradeItem(course->gradeitems[gisel], gisel + 1);
        displayFooter();
        displayEditGradeMenu();

        // operation selection
        int op;
        printf("Enter a number and choose an operation:");
        scanf("%d", &op);
        switch (op)
        {
        case 1:
            addGrade(&course->gradeitems[gisel]);
            break;
        case 2:
            deleteGrade(course, &course->gradeitems[gisel], gisel);
            break;
        case 3:
            deleteAllGrade(&course->gradeitems[gisel]);
            break;
        case 4:
            modifyGrade(course, &course->gradeitems[gisel], gisel);
            break;
        case 5:
            return; // exit
            break;
        default:
            printf("\nInvalid Operation!\n");
            break;
        }
    }
    return;
}

void addGrade(struct GradeItem *gradeitem)
{
    while (1)
    {
        int grade;
        printf("Enter a grade to added to the item or a negative number back:");
        scanf("%d", &grade);

        // if input is negative exit
        if (grade < 0)
            return;

        // check if input is valid
        if (grade >= 0 && grade <= gradeitem->fullmark)
        {
            // find and insert grade at the end
            int i = 0;
            while (1)
            {
                if (gradeitem->grades[i] == -1)
                {
                    gradeitem->grades[i] = grade;
                    break;
                }
                i++;
            }
        }
        else
        {
            printf("\nInvalid Grade!\n");
        }
    }
    return;
}

void deleteGrade(struct Course *course, struct GradeItem *gradeitem, int gisel)
{
    while (1)
    {
        displayHeader(*course);
        displayGradeItem(*gradeitem, gisel + 1);
        displayFooter();

        int no;
        printf("Enter the number of a grade to delete or any other key back:");
        scanf("%d", &no);

        // if no match then exit
        if (no <= 0 || no > MAXGRADES || gradeitem->grades[no - 1] == -1)
            return;

        // move forward
        int i = 0;
        while (1)
        {
            if (gradeitem->grades[no - 1 + i] == -1)
                break;
            gradeitem->grades[no - 1 + i] = gradeitem->grades[no + i];
            i++;
        }
    }
    return;
}

void deleteAllGrade(struct GradeItem *gradeitem)
{
    // set all grades to -1
    for (int i = 0; i < MAXGRADES; i++)
    {
        gradeitem->grades[i] = -1;
    }
    return;
}

void modifyGrade(struct Course *course, struct GradeItem *gradeitem, int gisel)
{
    while (1)
    {
        displayHeader(*course);
        displayGradeItem(*gradeitem, gisel + 1);
        displayFooter();

        int no;
        printf("Enter the number of a grade to modify or any other key back:");
        scanf("%d", &no);

        // if no match then exit
        if (no <= 0 || no > MAXGRADES || gradeitem->grades[no - 1] == -1)
            return;

        // input new grade
        int newgrade;
        printf("You want to change %s Grade %d from %.2f to:", gradeitem->name, no, gradeitem->grades[no - 1]);
        scanf("%d", &newgrade);

        // check if input is valid
        if (newgrade >= 0 && newgrade <= gradeitem->fullmark)
            gradeitem->grades[no - 1] = newgrade;
        else
            printf("\nInvalid Grade!\n");
    }
    return;
}

void displayHeader(struct Course course)
{
    printf("\n\t%s %s\n", course.code, course.name);
    printf("-----------------------------------\n");
    printf("| No.    | Item                 | Percentage | Full Mark  | Grades\n");
    return;
}
void displayFooter()
{
    printf("-----------------------------------\n");
    return;
}

void displayGradeItem(struct GradeItem gradeitem, int no)
{
    printf("| %d\t", no);
    printf("| %-*s", 20, gradeitem.name);
    printf("| %.6f  ", gradeitem.percentage);
    printf("| %.6f  | ", gradeitem.fullmark);

    // print grades
    int j = 0;
    while (gradeitem.grades[j] >= 0) // set all grades to -1 if empty
    {
        printf("%d. %.2f ", j + 1, gradeitem.grades[j]);
        j++;
    }
    printf("\n");
    return;
}

void displayEditGradeMenu()
{
    printf("\n============== Edit Grade ==============\n");
    printf("\t1. Add Grade\n");
    printf("\t2. Delete Grade\n");
    printf("\t3. Delete All Grades\n");
    printf("\t4. Modify Grade\n");
    printf("\t5. Back\n");
    printf("==========================================\n");
    return;
}

int displayCourses(struct Course *courses)
{
    // count courses
    int courseCount = getCourseNum(courses);

    // print course info
    printf("There're totally %d courses recorded:\n\n", courseCount);
    for (int j = 0; j < courseCount; j++)
    {
        printf("%d.\t%s\t%s\n", j + 1, courses[j].code, courses[j].name);
    }
    return courseCount;
}